package com.telrob.bytevm.instruct;

import java.util.List;

import com.telrob.bytevm.compile.Instruct;
import com.telrob.bytevm.compile.ReplaceCode;
import com.telrob.bytevm.utils.Define;
import com.telrob.bytevm.utils.ToolUtils;
import com.telrob.bytevm.vm.Register;

public class STORE implements Instruct {

	@Override
	public boolean isPseudo(String opt) {
		return false;
	}

	@Override
	public boolean isComplie(String opt) {
		if(opt.toLowerCase().startsWith("store")) {
			return true;
		}
		return false;
	}

	@Override
	public byte[] complie(String line, String[] param, int curretIndex, List<ReplaceCode> labelReplace) {
		byte[]data=null;
		if("storeb".equals(param[0].toLowerCase())||"storew".equals(param[0].toLowerCase())||"stored".equals(param[0].toLowerCase())||"stores".equals(param[0].toLowerCase())) {
			data=new byte[6];
			if("storeb".equals(param[0].toLowerCase())) {
				data[0]=Define.STOREB;
			} else if("storew".equals(param[0].toLowerCase())) {
				data[0]=Define.STOREW;
			} else if("stored".equals(param[0].toLowerCase())) {
				data[0]=Define.STORED;
			} else if("stores".equals(param[0].toLowerCase())) {
				data[0]=Define.STORES;
			}
			
			int number=0;
			try {
				//当不是数字时候就当标签来处理
				number=ToolUtils.parseNum(param[1]);
			}catch(Exception e) {
				ReplaceCode code=new ReplaceCode(param[1], curretIndex+1);
				labelReplace.add(code);
			}
			data[1]=(byte)(0xFF&(number>>0));
			data[2]=(byte)(0xFF&(number>>8));
			data[3]=(byte)(0xFF&(number>>16));
			data[4]=(byte)(0xFF&(number>>24));
			
			
			String o2=param[2].toLowerCase();
			if("ax".equals(o2)) {
				data[5]=Define.AX;
			}else if("bx".equals(o2)) {
				data[5]=Define.BX;
			}else if("cx".equals(o2)) {
				data[5]=Define.CX;
			}else if("dx".equals(o2)) {
				data[5]=Define.DX;
			}else if("ex".equals(o2)) {
				data[5]=Define.EX;
			}else if("ss".equals(o2)) {
				data[5]=Define.SS;
			}else if("si".equals(o2)) {
				data[5]=Define.SI;
			}else if("sp".equals(o2)) {
				data[5]=Define.SP;
			}else if("bp".equals(o2)) {
				data[5]=Define.BP;
			}else if("di".equals(o2)) {
				data[5]=Define.DI;
			}
			
		}
		return data;
	}

	@Override
	public int isRun(byte opt) {
		if(opt==Define.STOREB||opt==Define.STOREW||opt==Define.STORED||opt==Define.STORES) {
			return 6;
		}
		return -1;
	}

	@Override
	public void parseRun(Register R, byte opt, byte[] data) {
		if(opt==Define.STOREB||opt==Define.STOREW||opt==Define.STORED||opt==Define.STORES) {
			byte rx=data[R.PC+5];
			int dd=0;
			if(rx==Define.AX) {
				dd=R.AX;
			}else if(rx==Define.BX) {
				dd=R.BX;
			}else if(rx==Define.CX) {
				dd=R.CX;
			}else if(rx==Define.DX) {
				dd=R.DX;
			}else if(rx==Define.EX) {
				dd=R.EX;
			}else if(rx==Define.BP) {
				dd=R.BP;
			}else if(rx==Define.SS) {
				dd=R.SS;
			}else if(rx==Define.SP) {
				dd=R.SP;
			}
			int number=ToolUtils.getByte(data, R.PC+1);
			if(opt==Define.STOREB) {
				data[number]=(byte)(dd&0xFF);
			}else if(opt==Define.STOREW) {
				data[number]=(byte)(dd&0xFF);
				data[number+1]=(byte)(dd>>8&0xFF);
			}else if(opt==Define.STORED) {
				data[number]=(byte)(dd&0xFF);
				data[number+1]=(byte)(dd>>8&0xFF);
				data[number+2]=(byte)(dd>>16&0xFF);
				data[number+3]=(byte)(dd>>24&0xFF);
			}else if(opt==Define.STORES) {
				number=number+R.SS+R.BP;
				data[number]=(byte)(dd&0xFF);
				data[number+1]=(byte)(dd>>8&0xFF);
				data[number+2]=(byte)(dd>>16&0xFF);
				data[number+3]=(byte)(dd>>24&0xFF);
			}
			R.PC+=isRun(opt);
		}
		
	}

}
